{
module DataParser(parseString2Value, parseString,parseString2ValEnv)  where
import DataLexer
import DataUpdate
import Synchronizers
}

%name monadParse
%tokentype { Token }
%monad { Alex }
%lexer { dataLexer } { EOFToken }

%token
	Integer		{ IntegerConst _ }
	String		{ StringConst _ }
	True		{ TrueConst }
	False		{ FalseConst }
	Null		{ NullConst }
	'{'			{ Operator "{" }
	'}'			{ Operator "}" }
	'->'		{ Operator "->" }
    '='         { Operator "=" }
	'!'			{ Operator "!" }
	','			{ Operator "," }
	
%%
data :: { Value }
data : prim_value  { $1 }
     |  dictionary { $1 }

prim_value :: { Value }
prim_value : primitive { Prim $1 }
primitive :: {Prim}
primitive : Integer { (\(IntegerConst a) -> Int a) $1 }
           | String { (\(StringConst a) -> String a) $1 }
           | Null	{ Null }
           | True	{ String "@true" }
           | False	{ String "@false" }

dictionary :: { Value }
dictionary : '{' entries '}'    { Dict ($2 emptyDict) }
    | '{' '}'                   { Dict emptyDict }
entries : entry 	            { (\p -> p \\ $1) }
	| entry ',' entries         { (\p -> $3 (p \\ $1)) }
entry: primitive equalSign optionalExclamationMark data { ($1, $4) }
equalSign: '->' {} | '=' {}
optionalExclamationMark : '!' {} | {} 

{
parseString :: String -> Either String Value
parseString input = runAlex input monadParse

parseString2Value :: String -> Either String Value
parseString2Value input = parseString input

--applyRight :: (b -> c) -> Either a b -> Either a c
--applyRight f (Left a) = Left a
--applyRight f (Right b) = Right (f b) 

--parseString2Update :: String -> Either String Update
--parseString2Update = (applyRight toUpdate).parseString  
--    where toUpdate v | v == emptyDictValue = emptyDUpdate
--                     | otherwise  = findUpdate emptyDictValue v
                     
parseString2ValEnv :: String -> Either String ValEnv
parseString2ValEnv = parseString2ValEnv'.parseString
  where 
   parseString2ValEnv' (Left msg) = Left msg
   parseString2ValEnv' (Right (Dict v)) = Right (keepStringKeys v) 
   parseString2ValEnv' (Right _) = Left "error: not variables"
        
keepStringKeys :: (Eq a)=>DValMap Prim a -> DValMap Var a
keepStringKeys d = foldWithKey filter (empty (getDefaultValue d)) d
    where filter (String s) v d = d \\ (string2Var s, v)
          filter _ _ d = d   
                     
--parseString2UpdateEnv :: String -> Either String UpdateEnv
--parseString2UpdateEnv = parseString2UpdateEnv'.parseString2Update
--  where 
--  parseString2UpdateEnv' (Left msg) = Left msg
--  parseString2UpdateEnv' (Right (DUpdate v)) = Right (keepStringKeys v) 
--  parseString2UpdateEnv' (Right _) = Left "not an environment"

happyError :: Alex a
happyError = do
	line <- alexGetLine
	column <- alexGetColumn
	alexError ("line " ++ show line ++ ", column " ++ show column ++": parser error")

}